#include <iostream>
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <ctime>
#include "Task.hpp"

#ifndef __PROCESS_POOL_HPP
#define __PROCESS_POOL_HPP

class Channel
{
public:
    Channel(int fd = 0, int id = 0)
        : _wfd(fd), _subid(id)
    {
        _name = "Pipe[" + std::to_string(fd) + "]-" + "Child-" + std::to_string(id);
    }
    ~Channel()
    {
        ;
    }

    int Fd()
    {
        return _wfd;
    }

    int SubId()
    {
        return _subid;
    }

    std::string &Name()
    {
        return _name;
    }

    void Close()
    {
        close(_wfd);
    }

    void Stop()
    {
        int n = waitpid(_subid,nullptr,0);
        (void)n;
    }

private:
    int _wfd;
    int _subid;
    std::string _name;
};

class Channel_Magager
{
public:
    Channel_Magager() {}
    ~Channel_Magager() {}

    // 随机选择。
    // Channel& Select()
    // {
    //     srand(0);

    //     return _ch[rand() % _ch.size()];
    // }

    // 轮寻。
    Channel& Select()
    {
        ++_next;
        _next %= _ch.size();

        return _ch[_next];
    }

    void Debug()
    {
        for (auto &e : _ch)
        {
            std::cout << e.Name() << std::endl;
        }
    }

    void Insert(int wds , int id)
    {
        _ch.emplace_back(wds,id);
    }

    void ReverseCloseFD()
    {
        if(_ch.size() == 0)
        {
            return ;
        }

        int n = _ch.size() - 1;

        for(int i = n;i >= 0;--i)
        {
            _ch[i].Close();
        }
    }

    void ReverseStopSubid()
    {
        if(_ch.size() == 0)
        {
            return ;
        }
        
        int n = _ch.size() - 1;
        
        for(int i = n;i >= 0;--i)
        {
            _ch[i].Stop();
        }
    }

    void CloseFD()
    {
        for(auto& e : _ch)
        {
            e.Close();
        }
    }

    void StopSubid()
    {
        for(auto& e : _ch)
        {
            e.Stop();
        }
    }

    // bool Create()
    // {
    //     ;
    // }

    size_t size()
    {
        return _ch.size();
    }

    void Clean()
    {
        for(int i = 0;i < _ch.size();++i)
        {
            _ch[i].Close();
            _ch[i].Stop();
        }
    }
 
private:
    std::vector<Channel> _ch;
    int _next;
    int load;
};

class Process_Pool
{
public:
    Process_Pool(int n) 
        :_process_sum(n)
    {}
    ~Process_Pool() {}

    bool Send(int wfd)
    {
        srand(0);
        int code = rand();
        code %= _tm.size();
        ssize_t ret = write(wfd,&code,sizeof(code));

        if(ret > 0)
        {
            if(ret == sizeof(code))
            {
                return true;
            }
        }
            return false;
    } 

    // 子进程执行的代码。
    void Work(int rfd)
    {
        while(true)
        {
            int code = 0;
            ssize_t n = read(rfd,&code,sizeof(code));
            if(n > 0)
            {
                if(n != sizeof(code))
                {
                    continue;
                }
                std::cout << "子进程" << getpid() << "收到一个任务码" << code << std::endl;
                std::cout << "执行该任务码" << std::endl;
                (*(_tm[code].Value()))();
            }
            else if(n == 0)
            {
                std::cout << "子进程退出" << std::endl;
                break;
            }
            else
            {
                break;
            }

            //std::cout << "子进程pid:" << getpid() << "-" << code << std::endl;
        }
    }

    bool Start()
    {
        for(int i = 0;i < _process_sum;++i)
        {
            int fds[2] = { 0 };
            int rp = pipe(fds);

            if(rp != 0)
            {
                return false;
            }

            int id = fork();

            if(id == 0)
            {
                // 子进程
                // 负责读
                // 子进程没必要管理自己的pipe读端。
                close(fds[1]);
                //_cm.Insert(fds[0],id);
                Work(fds[0]);
                exit(0);
            }
            else
            {
                // 父进程
                // 负责写。
                close(fds[0]);
                _cm.Insert(fds[1],id);
            }
        }

        return true;
    }

    void Run()
    {
        Channel& c = _cm.Select();
        std::cout << c.Name() << std::endl;
        Send(c.Fd());
    }

    void Stop()
    {
        _cm.StopSubid();
    }

    void Wait()
    {
        _cm.StopSubid();
    }

    void StopAndClose()
    {
        // 关闭管道后，子进程就结束了。
        // 连贯一点，不过度等待。
        _cm.CloseFD();
        _cm.StopSubid();
    }

    // 因为StopAndClose函数封装的不够完全。
    // StopAndClose函数并不能清除所有子进程。
    // 因为在新的子进程会有一份父进程的拷贝。
    // 按照顺序删除旧子进程引用计数无法消除其他新进程对旧进程的影响。
    // 所以倒过来进行关闭，好弄。
    // 或是直接关闭所有新子进程的旧进程的。
    void Reverse_Stop_And_Close()
    {
        _cm.ReverseCloseFD();
        _cm.ReverseStopSubid();
    }

    // 关闭所有子进程。
    void CleanALLSon()
    {
        _cm.Clean();
    }

private:
    Channel_Magager _cm;
    int _process_sum;
    Tasks _tm;
};

#endif